<?php


namespace Streetlamp;


use Streetlamp\annotation\Mapping\Middleware;
use Streetlamp\annotation\Mapping\Service;
use Streetlamp\annotation\Mapping\ServiceMethod;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
use think\Exception;

class Scanner
{
    private $config;

    public function __construct($config = [])
    {
        $this->config = $config;
    }

    public function getPathClass()
    {
        $module = $this->config['module'] ?? '';//需要扫描的文件夹路径
        if (!$module)
            throw new Exception('service path not exist!');
        //PHP遍历文件夹下所有文件
        $handle = opendir(APP_PATH . DS . $module . '/logic/.');
        //扫描所有.php结尾的文件
        while (false !== ($file = readdir($handle))) {
            if ($file != '.' && $file != '..') {
                $base = strrchr($file, '.');
                if ($base == '.php')
                    $phpFileArr[] = substr($file, 0, strpos($file, '.')); //输出文件名
            }
        }
        closedir($handle);
        return $phpFileArr;
    }

    public function scan()
    {
        $phpFileArr = $this->getPathClass();
        AnnotationRegistry::registerLoader('class_exists');
        $reader = new AnnotationReader();
        foreach ($phpFileArr as $class) {
            $reflectionClass = new \ReflectionClass("app\\" . $this->config['module'] . "\logic\\" . $class);
            $myAnnotation    = $reader->getClassAnnotations($reflectionClass);
            foreach ($myAnnotation as $annotation) {
                if ($annotation instanceof Service) {
                    //收集有@Service注解的类
                    $classMap[] = $reflectionClass;
                }
            }
        }
        foreach ($classMap as $item) {
            $class = $item->newInstance();
            foreach ($item->getMethods() as $method) {
                $methodAnnotations = $reader->getMethodAnnotations($method, $method->name);
                foreach ($methodAnnotations as $methodAnnotation) {
                    if ($methodAnnotation instanceof ServiceMethod) {
                        $allMethod[] = ['class' => $class, 'method' => $method->name, 'alias' => $methodAnnotation->getServiceName()];
                    }
                }
            }
        }
        if (count($allMethod) != count(array_unique(array_column($allMethod, 'method')))) {
            throw new Exception('微服务的方法名不能重复');
        }
        return $allMethod;
    }
}